package com.central.apps.handler.project;

import com.central.app.common.base.BaseHandler;
import com.central.app.service.FlowCommonService;
import com.central.app.service.HandlerService;
import com.central.app.service.TreeService;
import com.central.app.service.VersionService;
import com.central.apps.service.TableService;
import com.central.apps.service.TaskService;
import com.central.bizcommon.model.flow.FlowNode;
import com.central.bizcommon.model.flow.FlowOpinion;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 处理任务变更业务逻辑
 *
 * @author lidachao
 * @date 2023/4/23
 */
@Component
@Slf4j
public class TaskChangeHandler extends BaseHandler {
    @Autowired
    private HandlerService handlerService;
    @Autowired
    private TreeService treeService;
    @Autowired
    private TableService tableService;
    @Autowired
    private VersionService versionService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private FlowCommonService flowCommonService;

    @Override
    public void beforSave(String app, String objName, Map<String, Object> data, boolean isUpdate) throws Exception {
        if (isUpdate && "gq_taskchange".equals(objName)) {
            Integer id = MapUtils.getInteger(data, "id");
            // 查询变更信息
            List<Map<String, Object>> list = handlerService.findBySql("select proid, taskid from gq_taskchange where id = " + id);
            Map<String, Object> map = list.get(0);
            Integer newProId = MapUtils.getInteger(data, "proid");
            Integer proId = MapUtils.getInteger(map, "proid");
            Integer newTaskid = MapUtils.getInteger(data, "taskid");
            Integer taskId = MapUtils.getInteger(map, "taskid");

            if (!newProId.equals(proId) || !newTaskid.equals(taskId)) {
                // 删除任务变更明细信息
                handlerService.updateBySql("delete from gq_taskchgdtl where tcid = " + id);

                // 删除任务变更详细信息
                handlerService.updateBySql("delete from gq_taskchgdtlchg where tcid = " + id);
                handlerService.updateBySql("delete from gq_taskchgdtlnew where tcid = " + id);
                handlerService.updateBySql("delete from gq_taskchgdtldel where tcid = " + id);

                // 删除交付物详细信息
                handlerService.updateBySql("delete from gq_tcdelichg where tcid = " + id);
                handlerService.updateBySql("delete from gq_tcdelichgdtl where tcid = " + id);
                handlerService.updateBySql("delete from gq_tcdelichgdel where tcid = " + id);
                handlerService.updateBySql("delete from gq_tcdelichgnew where tcid = " + id);
            }
        }
    }

    @Override
    public void afterSave(String app, String objName, Map<String, Object> data, boolean isUpdate) throws Exception {
        // 查询并保存任务信息到任务变更明细
        if ("gq_taskchange".equals(objName)) {
            Integer tcId = MapUtils.getInteger(data, "id");
            Integer proId = MapUtils.getInteger(data, "proid");
            Integer myTaskId = MapUtils.getInteger(data, "mytaskid");

            List<Map<String, Object>> list = handlerService.findBySql("select * from gq_taskchgdtl where tcid = " + tcId);
            if (CollectionUtils.isEmpty(list)) {
                Map<String, Object> params = new HashMap<>(4);
                params.put("tree_id", "id");
                params.put("tree_pid", "parentId");
                params.put("proid", proId);
                params.put("parent_filter", "id=" + myTaskId);
                List<Map<String, Object>> taskList = treeService.findTreeData("mytaskApp", params);

                if (CollectionUtils.isNotEmpty(taskList)) {
                    // 组织并插入任务变更数据
                    combineInsertData(proId, tcId, taskList);
                }
            }
        }
    }

    @Override
    public String beforeExcuteFlow(String app, Long id, FlowNode flowNode, FlowOpinion op) throws Exception {
        Map<String, Object> map = op.getVariables();
        if ("capture".equals(flowNode.getId())) {
            List<Map<String, Object>> list = handlerService.findBySql("select * from gq_taskchgdtl where tcid = " + id);
            if (CollectionUtils.isEmpty(list)) {
                return "请维护需要变更的任务!";
            }

            // WBS任务是否存在负责人为空数据
            list = handlerService.findBySql("select * from gq_taskchgdtl where (manager = 0 or manager is null) and tcid = " + id);

            if (CollectionUtils.isNotEmpty(list)) {
                return "存在任务未分配负责人!";
            }

            // 更新WBS任务只读
            handlerService.updateBySql("update gq_taskchgdtl set isreadonly = 1 where tcid = " + id);

            // 删除任务变更详细信息
            handlerService.updateBySql("delete from gq_taskchgdtlchg where tcid = " + id);
            handlerService.updateBySql("delete from gq_taskchgdtlnew where tcid = " + id);
            handlerService.updateBySql("delete from gq_taskchgdtldel where tcid = " + id);

            // 删除交付物详细信息
            handlerService.updateBySql("delete from gq_tcdelichgdtl where tcid = " + id);
            handlerService.updateBySql("delete from gq_tcdelichgdel where tcid = " + id);
            handlerService.updateBySql("delete from gq_tcdelichgnew where tcid = " + id);

            // 存储任务的变更和新增信息
            Integer proId = MapUtils.getInteger(map, "proid");
            Integer myTaskId = MapUtils.getInteger(map, "mytaskid");

            // 组织变更信息
            combineTaskInfo(proId, id.intValue(), myTaskId);
        }

        if("complete".equals(flowNode.getId()) && op.isFlag()) {
            Integer proId = MapUtils.getInteger(map, "proid");
            Integer myTaskId = MapUtils.getInteger(map, "mytaskid");

            // 处理任务变更信息
            dealTask(proId, id.intValue(), myTaskId);
        }
        return null;
    }

    @Override
    public void afterMoveNode(String app, Long id) throws Exception {
        Map<String, Object> map = handlerService.findOneBySql("select status from gq_taskchange where id = " + id);
        boolean isReturnInitNode = flowCommonService.isSubmitNode(app, id);

        if (isReturnInitNode) {
            handlerService.updateBySql("update gq_taskchgdtl set isreadonly = 0 where tcid = " + id);
        }
    }

    /**
     * 存储任务的变更和新增信息
     *
     * @param proId
     * @param tcId
     */
    private void combineTaskInfo(Integer proId, Integer tcId, Integer myTaskId) throws Exception {
        // 查询并保存计划版本信息
        Map<String, Object> params = new HashMap<>(4);
        params.put("tree_id", "id");
        params.put("tree_pid", "parentId");
        params.put("proid", proId);
        params.put("parent_filter", "id=" + myTaskId);
        List<Map<String, Object>> myTaskList = treeService.findTreeData("mytaskApp", params);

        // 查询是否保存了任务计划数据
        List<Map<String, Object>> taskChgList = handlerService.findBySql("select * from gq_taskchgdtl where tcid = " + tcId);

        if (CollectionUtils.isNotEmpty(taskChgList)) {
            Map<String, List<String>> convertMap = new HashMap<>();
            convertMap.computeIfAbsent("description", key -> new ArrayList<>()).add("newdescription");
            convertMap.computeIfAbsent("startTime", key -> new ArrayList<>()).add("newstartTime");
            convertMap.computeIfAbsent("endTime", key -> new ArrayList<>()).add("newendTime");
            convertMap.computeIfAbsent("duration", key -> new ArrayList<>()).add("newduration");
            convertMap.computeIfAbsent("managername", key -> new ArrayList<>()).add("newmanagername");
            convertMap.computeIfAbsent("predecessorsdesc", key -> new ArrayList<>()).add("newpredecessorsdesc");
            convertMap.computeIfAbsent("assignsdesc", key -> new ArrayList<>()).add("newassignsdesc");
            convertMap.computeIfAbsent("parentname", key -> new ArrayList<>()).add("newparentname");
            convertMap.computeIfAbsent("iswarnflag", key -> new ArrayList<>()).add("newiswarnflag");
            convertMap.computeIfAbsent("taskrisk", key -> new ArrayList<>()).add("newtaskrisk");
            convertMap.computeIfAbsent("controlmeasures", key -> new ArrayList<>()).add("newcontrolmeasures");
            convertMap.computeIfAbsent("tasklevel", key -> new ArrayList<>()).add("newtasklevel");

            List<String> expFields = new ArrayList<>();
            expFields.add("id");
            expFields.add("createtime");
            expFields.add("createuser");
            expFields.add("createuserdesc");
            expFields.add("updatetime");
            expFields.add("updateuser");
            expFields.add("status");
            expFields.add("taskstatus");
            expFields.add("version");
            expFields.add("recordId");
            expFields.add("uniqueId");
            expFields.add("hasChild");
            expFields.add("isissued");

            // 处理变更信息->显示的展示WBS变化数据
            taskService.dealChgInfo("taskchangeApp", "tcid", tcId, "gq_taskchgdtl", "mytaskid", "gq_mytask", "gq_taskchgdtlchg",
                    "gq_taskchgdtlnew", "gq_taskchgdtldel", taskChgList, myTaskList, convertMap, expFields);

            // 查询交付物变更信息
            // tctaskid not in (select id from gq_taskchgdtl where istemptask = '1' and tcid = " + tcId + ") and
            List<Map<String, Object>> chgList = handlerService.findBySql("select * from gq_tcdelichg where tcid = " + tcId);
            // 查询交付物计划信息
            StringBuilder taskIds = new StringBuilder();
            for (Map<String, Object> myTaskMap : myTaskList) {
                Integer taskId = MapUtils.getInteger(myTaskMap, "taskid");
                taskIds.append(taskId).append(",");
            }
            taskIds.deleteCharAt(taskIds.length() - 1);

            List<Map<String, Object>> deliList = handlerService.findBySql("select * from gq_taskdeliverables where proid = " + proId + " and taskid in (" + taskIds.toString() + ")");

            convertMap = new HashMap<>();
            convertMap.computeIfAbsent("delname", key -> new ArrayList<>()).add("newdelname");
            convertMap.computeIfAbsent("deltype", key -> new ArrayList<>()).add("newdeltype");
            convertMap.computeIfAbsent("delcategory", key -> new ArrayList<>()).add("newdelcategory");
            convertMap.computeIfAbsent("remarks", key -> new ArrayList<>()).add("newremarks");
            convertMap.computeIfAbsent("isprodeli", key -> new ArrayList<>()).add("newisprodeli");
            convertMap.computeIfAbsent("deltypeid", key -> new ArrayList<>()).add("newdeltypeid");
            convertMap.computeIfAbsent("deltypenum", key -> new ArrayList<>()).add("newdeltypenum");
            convertMap.computeIfAbsent("delcategoryid", key -> new ArrayList<>()).add("newdelcategoryid");
            convertMap.computeIfAbsent("delcategorynum", key -> new ArrayList<>()).add("newdelcategorynum");

            expFields = new ArrayList<>();
            expFields.add("id");
            expFields.add("createtime");
            expFields.add("createuser");
            expFields.add("createuserdesc");
            expFields.add("updatetime");
            expFields.add("updateuser");
            expFields.add("status");
            expFields.add("version");
            expFields.add("olddeliid");
            expFields.add("tcid");
            expFields.add("tctaskid");

            // 处理交付物变更信息
            taskService.dealChgInfo("taskchangeApp", "tcid", tcId, "gq_tcdelichg", "olddeliid", "gq_taskdeliverables", "gq_tcdelichgdtl",
                    "gq_tcdelichgnew", "gq_tcdelichgdel", chgList, deliList, convertMap, expFields);
        }
    }

    /**
     * 处理项目计划变更信息
     *
     * @param proId
     * @param tcId
     */
    private void dealTask(Integer proId, Integer tcId, Integer myTaskId) throws Exception {
        // 查询我的任务信息
        Map<String, Object> params = new HashMap<>(4);
        params.put("tree_id", "id");
        params.put("tree_pid", "parentId");
        params.put("proid", proId);
        params.put("parent_filter", "id=" + myTaskId);
        List<Map<String, Object>> myTaskList = treeService.findTreeData("mytaskApp", params);

        // 查询是否保存了任务计划数据
        List<Map<String, Object>> taskChgList = handlerService.findBySql("select * from gq_taskchgdtl where tcid = " + tcId);

        Map<Integer, Integer> relateMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(taskChgList)) {
            // 赋值项目信息
            Integer personInCharge = MapUtils.getInteger(taskChgList.get(0), "personincharge");
            Integer proLeader = MapUtils.getInteger(taskChgList.get(0), "proleader");
            String subjectNo = MapUtils.getString(taskChgList.get(0), "subjectno");

            Map<String, Object> setValues = new HashMap<>();
            setValues.put("personincharge", personInCharge);
            setValues.put("proleader", proLeader);
            setValues.put("subjectno", subjectNo);
            setValues.put("isissued", 1);
            setValues.put("status", "未开始");
            setValues.put("taskstatus", "未开始");
            setValues.put("isreadonly", 1);

            List<String> filterFields = new ArrayList<>();
            filterFields.add("taskid");
            filterFields.add("tcid");

            // 插入新增任务到我的任务
            taskService.insertChgInfo(relateMap, "gq_mytask", "mytaskid", taskChgList, setValues
                    , filterFields, true, "gq_taskchgdtl", false, null, true, "parentId");

            Map<String, String> relateConvertMap = new HashMap<>();
            relateConvertMap.put("id", "taskid");

            List<String> expFields = new ArrayList<>();
            expFields.add("id");
            expFields.add("createtime");
            expFields.add("createuser");
            expFields.add("createuserdesc");
            expFields.add("updatetime");
            expFields.add("updateuser");
            expFields.add("status");
            expFields.add("taskstatus");
            expFields.add("version");
            expFields.add("recordId");
            expFields.add("uniqueId");
            expFields.add("hasChild");
            expFields.add("isissued");

            // 更新任务信息到我的任务或删除我的任务
            taskService.updateDeleteChgInfo(relateMap, relateConvertMap, taskChgList, myTaskList,
                    filterFields, "gq_mytask", false, "mytaskid", expFields, true, "parentId");

            // 更新任务信息
            taskService.updateTaskInfo("gq_mytask", "proid = " + proId, "level");

            // 插入新增任务到我的任务
            relateMap.clear();

            // 查询最新我的任务信息
            myTaskList = handlerService.findBySql("select * from gq_mytask where proid = " + proId + " order by recordId");
            // 查询并保存计划版本信息
            List<Map<String, Object>> proTaskList = handlerService.findBySql("select * from gq_scheduleplantask where proid = " + proId + " order by recordId");

            filterFields = new ArrayList<>(2);
            filterFields.add("taskid");
            filterFields.add("tcid");
            // 插入新增任务到WBS计划
            taskService.insertChgInfo(relateMap, "gq_scheduleplantask", "taskid", myTaskList, setValues
                    , filterFields, true, "gq_mytask", true, "istemptask", true, "parentId");

            // 保存WBS计划版本
            if (relateMap != null && !relateMap.isEmpty() && CollectionUtils.isNotEmpty(proTaskList)) {
                String conditionStr = " proid = " + proId;
                versionService.saveData("gq_scheduleplantask", conditionStr, proTaskList);
            }

            relateConvertMap = new HashMap<>();
            relateConvertMap.put("id", "taskid");

            // 更新任务信息到WBS计划或删除WBS计划
            taskService.updateDeleteChgInfo(relateMap, relateConvertMap, myTaskList, proTaskList,
                    filterFields, "gq_scheduleplantask", true, "taskid", expFields, true, "parentId");

            // 更新WBS计划信息
            taskService.updateTaskInfo("gq_scheduleplantask", "proid = " + proId, "level");

            // 交付物处理
            setValues = new HashMap<>();
            setValues.put("status", "未交付");

            expFields = new ArrayList<>();
            expFields.add("tcid");
            expFields.add("tctaskid");
            expFields.add("mytaskid");

            // 更新新增的交付物计划任务id
            List<Map<String, Object>> newDeliList = handlerService.findBySql("select id, tctaskid from gq_tcdelichgnew where tcid = " + tcId);
            if (CollectionUtils.isNotEmpty(newDeliList)) {
                for (Map<String, Object> newDeliMap : newDeliList) {
                    Integer tcTaskId = MapUtils.getInteger(newDeliMap, "tctaskid");
                    Map<String, Object> myTaskMap = handlerService.findOneBySql("select taskid from gq_mytask where id in (select mytaskid from gq_taskchgdtl where tcid = "+tcId+" and id = "+tcTaskId+")");

                    if (myTaskMap != null && !myTaskMap.isEmpty()) {
                        Integer tempTaskId = MapUtils.getInteger(myTaskMap, "taskid");

                        Map<String, Object> updMap = new HashMap<>();
                        updMap.put("id", MapUtils.getInteger(newDeliMap, "id"));
                        updMap.put("taskid", tempTaskId);
                        handlerService.update("gq_tcdelichgnew", updMap);
                    }
                }
            }

            taskService.dealDeliverables("proplanApp", "tcid = " + tcId, "olddeliid", "gq_tcdelichgnew",
                    "gq_tcdelichgdtl", "gq_tcdelichgdel", "gq_taskdeliverables", setValues, expFields, null);
        }
    }

    /**
     * 组织并插入任务变更数据
     *
     * @param taskList
     */
    private void combineInsertData(Integer proId, Integer tcId, List<Map<String, Object>> taskList) throws Exception {
        if (CollectionUtils.isNotEmpty(taskList)) {
            Map<String, List<String>> convertMap = new HashMap<>();
            convertMap.computeIfAbsent("id", key -> new ArrayList<>()).add("mytaskid");
            convertMap.computeIfAbsent("templevel", key -> new ArrayList<>()).add("taskchglevel");

            List<Map<String, Object>> insertList = new ArrayList<>();
            for (Map<String, Object> map : taskList) {
                Map<String, Object> addMap = tableService.convertMap("gq_mytask", "gq_taskchgdtl", map, convertMap, null);
                addMap.put("tcid", tcId);// 任务变更id
                addMap.put("status", map.get("status"));// 状态
                addMap.put("taskchgparentlevel", MapUtils.getInteger(map,"templevel") - 1);
                insertList.add(addMap);
            }

            if (CollectionUtils.isNotEmpty(insertList)) {
                handlerService.batchInsert("taskchangeApp", "gq_taskchgdtl", insertList);

                // 转换前置和父级集合
                taskService.updParentIdAndPredecessors("taskchangeApp", "gq_taskchgdtl", "proid = " + proId + " and tcid = " + tcId);
            }

            // 复制交付物信息
            StringBuilder sb = new StringBuilder();
            for (Map<String, Object> map : taskList) {
                sb.append(MapUtils.getInteger(map, "taskid")).append(",");
            }

            if (StringUtils.isNotEmpty(sb.toString())) {
                insertList = new ArrayList<>();
                sb.deleteCharAt(sb.length() - 1);

                // 查询项目计划交付物信息
                List<Map<String, Object>> deliList = handlerService.findBySql("select * from gq_taskdeliverables where taskid in (" + sb.toString() + ")");

                convertMap = new HashMap<>();
                convertMap.computeIfAbsent("id", key -> new ArrayList<>()).add("olddeliid");

                if (CollectionUtils.isNotEmpty(deliList)) {
                    // 任务变更任务信息
                    List<Map<String, Object>> chgTaskList = handlerService.findBySql("select * from gq_taskchgdtl where tcid = " + tcId);

                    for (Map<String, Object> deliMap : deliList) {
                        Map<String, Object> addMap = tableService.convertMap("gq_tcdelichg", "gq_taskdeliverables", deliMap, convertMap, null);
                        // 手工赋值信息
                        addMap.put("tcid", tcId);
                        addMap.put("status", deliMap.get("status"));

                        if (CollectionUtils.isNotEmpty(chgTaskList)) {
                            Integer taskId = MapUtils.getInteger(deliMap, "taskid");
                            for (Map<String, Object> chgTaskMap : chgTaskList) {
                                Integer tempTaskId = MapUtils.getInteger(chgTaskMap, "taskid");

                                if (taskId.equals(tempTaskId)) {
                                    Integer tcTaskId = MapUtils.getInteger(chgTaskMap, "id");
                                    Integer myTaskId = MapUtils.getInteger(chgTaskMap, "mytaskid");

                                    addMap.put("mytaskid", myTaskId);
                                    addMap.put("tctaskid", tcTaskId);
                                    break;
                                }
                            }
                        }

                        insertList.add(addMap);
                    }

                    if (CollectionUtils.isNotEmpty(insertList)) {
                        handlerService.batchInsert("taskchangeApp", "gq_tcdelichg", insertList);
                    }
                }
            }
        }
    }
}
